PATHMac OS 8 Developer Documentation > Operating System Services > Multiprocessing Services >

Adding Multitasking Capability to Applications Using Multiprocessing Services

   

Calculating the Intertask Signaling Time

When using Multiprocessing Services tasks, the amount of time used by the task should be much greater than the time taken to pass notifications to the task. This intertask signaling time is generally between 20 and 50 microseconds. If you want to explicitly calculate the signaling time, you can use the code in Listing A-1 to do so.

Listing A-1   Calculating the intertask signaling time

#include <Multiprocessing.h>

#include <Types.h>
#include <stdio.h>
#include <stdlib.h>
#include <sioux.h>
#include <math64.h>
#include <DriverServices.h>


enum {
    aQueue = 0,
    aSemaphore,
    anEvent
} reflectOP;

MPOpaqueID waiterID, postID;


static OSStatus Reflector ( )
{
    void*p1,*p2,*p3;
    MPEventFlags events;

    while (true)
    {
        switch (reflectOP)
        {
            case aQueue:
                MPWaitOnQueue((MPQueueID) waiterID, &p1, &p2, &p3, kDurationForever);
                break;
                
            case aSemaphore:
                MPWaitOnSemaphore((MPSemaphoreID) waiterID, kDurationForever);
                break;
                
            case anEvent:
                MPWaitForEvent((MPEventID) waiterID, &events, kDurationForever);
                break;
                
            default:
                return -123;
        }

        switch (reflectOP)
        {
            case aQueue:
                MPNotifyQueue((MPQueueID) postID, &p1, &p2, &p3);
                break;
                
            case aSemaphore:
                MPSignalSemaphore((MPSemaphoreID) postID);
                break;
                
            case anEvent:
                MPSetEvent((MPEventID) postID, 0x01010101);
                break;
                
            default:
                return -123;
        }
    }
    
    return -123;
}


static float HowLong(
    AbsoluteTime endTime,
    AbsoluteTime bgnTime
    )
{
    AbsoluteTime absTime;
    Nanoseconds nanosec;
    
    absTime = SubAbsoluteFromAbsolute(endTime, bgnTime);
    nanosec = AbsoluteToNanoseconds(absTime);
    return (float) UnsignedWideToUInt64( nanosec ) / 1000.0;
}


void main ( void )
{
    OSStatus    err;
    MPTaskID    task;
    UInt32          i, count;
    void            *p1,*p2,*p3;
    MPEventFlags events;
    AbsoluteTime nowTime, bgnTime;
    float           uSec;
    char            buff[10];


    /* Set the console window defaults */
    /* (this is a Metrowerks CodeWarrior thing). */
    SIOUXSettings.autocloseonquit = true;
    SIOUXSettings.asktosaveonclose = false;
    SIOUXSettings.showstatusline = false;
    SIOUXSettings.columns = 100;
    SIOUXSettings.rows = 20;
    SIOUXSettings.fontsize = 10;
//  SIOUXSettings.fontid = monaco;
    SIOUXSettings.standalone = true;


//  DebugStr ( "\pStarting" );

    /*  Can't get very far without this one. */
    if  (!MPLibraryIsLoaded())
    {
        printf("The MP library did not load.\n");
        return;
    }


    /*  Find the overhead up UpTime. Perform a bunch of calls to average out */
    /*   cache effects. */
    printf("\n");
    
    bgnTime = UpTime();
    for (i=0; i<16; i++)
    {
        nowTime = UpTime();
    }

    uSec = HowLong(nowTime, bgnTime);
    uSec /= 16.0;
    printf(" UpTime overhead: %.3f usec \n", uSec);

    /*  Time intertask communication. */
    printf("\n Queues\n");

    reflectOP = aQueue;
    MPCreateQueue((MPQueueID*) &waiterID);
    MPCreateQueue((MPQueueID*) &postID);
    
    bgnTime = UpTime();
    err = MPCreateTask( Reflector,
                 NULL,
                 0,
                 NULL,
                 0,
                 0,
                 kNilOptions,
                 &task );
    nowTime = UpTime();
    uSec = HowLong(nowTime, bgnTime);
    printf(" MPCreateTask overhead: %.3f usec (may vary significantly) \n", uSec);
    if (err != noErr)
    {
        printf(" Task not created!\n");
        return;
    }

    count = 100000;
    bgnTime = UpTime();
    for (i=0; i<count; i++)
    {
        MPNotifyQueue((MPQueueID) waiterID, 0, 0, 0);
        while (true)
        {
            err = MPWaitOnQueue((MPQueueID) postID, &p1, &p2, &p3, kDurationImmediate);
            if (err != kMPTimeoutErr) break;
        }
    }
    nowTime = UpTime();
    uSec = HowLong(nowTime, bgnTime);
    uSec /= ((float) count / 2.0); // Two trips.
    printf(" Intertask signalling using queues overhead: %.3f usec \n", uSec);

    /*  Time intertask communication.
    */
    MPTerminateTask(task, 123);
    printf("\n Semaphores\n");

    reflectOP = aSemaphore;

    MPCreateSemaphore(1, 0, (MPSemaphoreID*) &waiterID);
    MPCreateSemaphore(1, 0, (MPSemaphoreID*) &postID);
    
    bgnTime = UpTime();
    err = MPCreateTask( Reflector,
                 NULL,
                 0,
                 NULL,
                 0,
                 0,
                 kNilOptions,
                 &task );
    nowTime = UpTime();
    uSec = HowLong(nowTime, bgnTime);
    printf(" MPCreateTask overhead: %.3f usec (may vary significantly) \n", uSec);
    if (err != noErr)
    {
        printf(" Task not created!\n");
        return;
    }

    count = 100000;
    bgnTime = UpTime();
    for (i=0; i<count; i++)
    {
        MPSignalSemaphore((MPSemaphoreID) waiterID);
        while (true)
        {
            err = MPWaitOnSemaphore((MPSemaphoreID) postID, kDurationImmediate);
            if (err != kMPTimeoutErr) break;
        }
    }
    nowTime = UpTime();
    uSec = HowLong(nowTime, bgnTime);
    uSec /= ((float) count / 2.0);// Two trips.
    printf(" Intertask signalling using sempahores overhead: %.3f usec \n", uSec);


    /*  Time intertask communication. */
    MPTerminateTask(task, 123);
    printf("\n Event Groups\n");

    reflectOP = anEvent;
    MPCreateEvent((MPEventID*) &waiterID);
    MPCreateEvent((MPEventID*) &postID);
    
    bgnTime = UpTime();
    err = MPCreateTask( Reflector,
                 NULL,
                 0,
                 NULL,
                 0,
                 0,
                 kNilOptions,
                 &task );
    nowTime = UpTime();
    uSec = HowLong(nowTime, bgnTime);
    printf(" MPCreateTask overhead: %.3f usec (may vary significantly) \n", uSec);
    if (err != noErr)
    {
        printf(" Task not created!\n");
        return;
    }

    count = 100000;
    bgnTime = UpTime();
    for (i=0; i<count; i++)
    {
        MPSetEvent((MPEventID) waiterID, 0x01);
        while (true)
        {
            err = MPWaitForEvent((MPEventID) postID, &events, kDurationImmediate);
            if (err != kMPTimeoutErr) break;
        }
    }
    nowTime = UpTime();
    uSec = HowLong(nowTime, bgnTime);
    uSec /= ((float) count / 2.0);// Two trips.
    printf(" Intertask signalling using events overhead: %.3f usec \n", uSec);

    gets(buff);

}

© 1999 Apple Computer, Inc. – (Last Updated 07 May 99)